#ifndef GRAPH_H
#define GRAPH_H

#include "Olor.h"

#include <vector>

using namespace std;

/**
 * Este es el grafo de caminos del escenario.
 *
 * Se modela con una matris de adyacencias.
 */
class Node {
    friend class Graph;

  private:
        /**
         * Identificador unico del nodo.
         * Ademas, indica la posicion en el vector de Nodos del grafo
         * en el que este nodo se encuentra.
         * Rango: [0 ... ]
         */
        int id;

        // Lo modelamos como un vector [3] por compactibilidad
        float position[2];

        /** costo particular del nodo*/
        float costSoFar;

        /** Usado en la busqueda de caminos */
        Node *connection;

        /** Lista de vecinos */
        vector<Node *>neighbors;

  public:
    vector<Olor *>olores;

    Node(float x=0, float y=0);

        float getCost();

        int getId();

        void setPosition(float x, float y);

        /**
         * Obtiene la lista completa de nodos
         */
        vector<Node *> getNeighbors();

        /**
         * Obtiene el vector pocision del nodo
         */
        const float* getPosition();

        /**
         * Con esto se obtienen directamente las coordenadas
         * del nodo
         */
        float operator[](int i) const;

        void addOlor(Olor* olor);
};

class Graph {
    public:
      vector<Node *>nodes;

    public:
        Graph();

        /**
         * Obtiene el i-esimo nodo
         */
        const Node *getNode(int i);

        /**
         * Obtiene la lista completa de nodos
         */
        vector<Node *> getNodes();

        /**
         * Agrega un Nodo al grafo
         */
        void addNode(Node *a);

        /**
         * Agrega una arista al grafo.
         */
        void addEdge(Node *a, Node *b);
        void addEdge(int a, int b);

        /**
         * Agrega las aristas (a,b) y (b,a)
         */
        void addDoubleEdge(Node *a, Node *b);
        void addDoubleEdge(int a, int b);

        /**
         * Aplica el algoritmo de Dijkstra
         * @return Vector con los nodos que indican el camino encontrado.
         */
        vector<Node *> dijkstra(Node *start, Node *end);
        void _dijkstra_inicializeNode(Node *n);
        bool _dijkstra_inList(vector<Node *>*list, Node *node);

        Node *findNearestNode(float point[2]);
};

extern Graph graph;
extern Graph graph_heal;
extern Graph graph_cover;

float costNodePath(vector<Node *>path);

#endif
